/**
 * @file dbus_server.c
 * @brief D-Bus服务端测试程序 - 接收信号和处理方法调用
 */
#include "dbus_common.h"

static DBusConnection *g_connection = NULL;

static int register_method_handler(const char *interface, const char *member,
                                   DBusHandlerResult (*handler)(DBusConnection *connection, DBusMessage *message))
{
    if (g_method_handler_count >= 32 || !interface || !member || !handler)
    {
        fprintf(stderr, "注册方法处理器失败：参数无效或已达到最大数量\n");
        return FALSE;
    }

    strncpy(g_method_handlers[g_method_handler_count].interface, interface, 255);
    g_method_handlers[g_method_handler_count].interface[255] = '\0';

    strncpy(g_method_handlers[g_method_handler_count].member, member, 127);
    g_method_handlers[g_method_handler_count].member[127] = '\0';

    g_method_handlers[g_method_handler_count].handler = handler;
    g_method_handler_count++;

    printf("已注册方法处理器: %s.%s\n", interface, member);
    return TRUE;
}

/**
 * @brief 注册信号处理器
 */
static int register_signal_handler(const char *interface, const char *member,
                                   void (*handler)(DBusMessage *message))
{
    if (g_signal_handler_count >= 32 || !interface || !member || !handler)
    {
        fprintf(stderr, "注册信号处理器失败：参数无效或已达到最大数量\n");
        return FALSE;
    }

    strncpy(g_signal_handlers[g_signal_handler_count].interface, interface, 255);
    g_signal_handlers[g_signal_handler_count].interface[255] = '\0';

    strncpy(g_signal_handlers[g_signal_handler_count].member, member, 127);
    g_signal_handlers[g_signal_handler_count].member[127] = '\0';

    g_signal_handlers[g_signal_handler_count].handler = handler;
    g_signal_handler_count++;

    printf("已注册信号处理器: %s.%s\n", interface, member);
    return TRUE;
}

/**
 * @brief 处理测试方法调用
 */
static DBusHandlerResult handle_test_method_call(DBusConnection *connection, DBusMessage *message)
{
    DBusMessage *reply = NULL;
    DBusMessageIter input_args, reply_args;
    char *param = NULL;
    const char *response = "服务端回复";

    /* 读取参数 */
    if (dbus_message_iter_init(message, &input_args))
    {
        if (DBUS_TYPE_STRING == dbus_message_iter_get_arg_type(&input_args))
        {
            dbus_message_iter_get_basic(&input_args, &param);
            printf("测试方法参数: %s\n", param ? param : "(null)");
        }
        else
        {
            fprintf(stderr, "测试方法参数类型不正确\n");
            reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                           "Expected string parameter");
            if (reply)
            {
                dbus_connection_send(connection, reply, NULL);
                dbus_connection_flush(connection);
                dbus_message_unref(reply);
            }
            return DBUS_HANDLER_RESULT_HANDLED;
        }
    }

    /* 创建并发送回复 */
    reply = dbus_message_new_method_return(message);
    if (!reply)
    {
        return DBUS_HANDLER_RESULT_NEED_MEMORY;
    }

    dbus_message_iter_init_append(reply, &reply_args);
    if (!dbus_message_iter_append_basic(&reply_args, DBUS_TYPE_STRING, &response))
    {
        dbus_message_unref(reply);
        return DBUS_HANDLER_RESULT_NEED_MEMORY;
    }

    dbus_connection_send(connection, reply, NULL);
    dbus_connection_flush(connection);
    dbus_message_unref(reply);

    return DBUS_HANDLER_RESULT_HANDLED;
}

/**
 * @brief 初始化服务端
 */
static int initialize_server()
{
    DBusError error;
    int ret;

    dbus_error_init(&error);

    /* 连接到会话总线 */
    g_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
    if (dbus_error_is_set(&error))
    {
        fprintf(stderr, "连接D-Bus失败: %s\n", error.message);
        dbus_error_free(&error);
        return FALSE;
    }

    if (!g_connection)
    {
        fprintf(stderr, "连接D-Bus失败，返回NULL连接\n");
        return FALSE;
    }

    /* 请求服务名 */
    ret = dbus_bus_request_name(g_connection, TEST_SERVICE_NAME,
                                DBUS_NAME_FLAG_REPLACE_EXISTING, &error);
    if (dbus_error_is_set(&error))
    {
        fprintf(stderr, "请求服务名失败: %s\n", error.message);
        dbus_error_free(&error);
        dbus_connection_unref(g_connection);
        g_connection = NULL;
        return FALSE;
    }

    switch (ret)
    {
    case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
        printf("成功获取服务名: %s\n", TEST_SERVICE_NAME);
        break;
    case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
        fprintf(stderr, "服务名已被占用，已加入等待队列\n");
        break;
    case DBUS_REQUEST_NAME_REPLY_EXISTS:
        fprintf(stderr, "服务名已存在且无法替换\n");
        dbus_connection_unref(g_connection);
        g_connection = NULL;
        return FALSE;
    case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
        printf("已经拥有服务名: %s\n", TEST_SERVICE_NAME);
        break;
    default:
        fprintf(stderr, "请求服务名返回未知状态: %d\n", ret);
        dbus_connection_unref(g_connection);
        g_connection = NULL;
        return FALSE;
    }

    printf("服务端初始化成功\n");
    /* 添加过滤器注册 ，使用 dbus_connection_read_write_dispatch 时，该函数内部已经会自动调用消息过滤器和处理器来处理消息*/
    dbus_connection_add_filter(g_connection, message_filter, NULL, NULL);
    return TRUE;
}

/**
 * @brief 设置信号监听器 - 支持多个信号
 */
static int setup_signal_listeners()
{
    DBusError error;
    if (!check_connection_status())
    {
        fprintf(stderr, "D-Bus连接状态异常\n");
        goto cleanup;
    }

    dbus_error_init(&error);

    /* 为每个注册的信号处理器添加匹配规则 */
    for (int i = 0; i < g_signal_handler_count; i++)
    {
        snprintf(g_match_rules[g_match_rule_count], sizeof(g_match_rules[0]),
                 "type='signal',interface='%s',member='%s'",
                 g_signal_handlers[i].interface, g_signal_handlers[i].member);

        dbus_bus_add_match(g_connection, g_match_rules[g_match_rule_count], &error);
        if (dbus_error_is_set(&error))
        {
            fprintf(stderr, "添加信号匹配规则失败: %s\n", error.message);
            dbus_error_free(&error);
            return FALSE;
        }

        printf("信号监听规则已添加: %s\n", g_match_rules[g_match_rule_count]);
        g_match_rule_count++;
    }

    return TRUE;
}

/**
 * @brief 处理测试信号
 */
static void handle_test_signal(DBusMessage *message)
{
    DBusMessageIter args;
    char *param = NULL;

    if (!dbus_message_iter_init(message, &args))
    {
        printf("测试信号没有参数\n");
        return;
    }

    if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
    {
        printf("测试信号参数类型不正确\n");
        return;
    }

    dbus_message_iter_get_basic(&args, &param);
    printf("测试信号内容: %s\n", param ? param : "(null)");
}

/**
 * @brief 处理接收到的信号
 */
static void handle_signal_default(DBusMessage *message)
{
    DBusMessageIter args;
    char *param = NULL;

    printf("收到信号: %s.%s\n", dbus_message_get_interface(message),
           dbus_message_get_member(message));

    /* 读取信号参数 */
    if (!dbus_message_iter_init(message, &args))
    {
        printf("信号没有参数\n");
    }
    else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
    {
        printf("信号参数类型不正确\n");
    }
    else
    {
        dbus_message_iter_get_basic(&args, &param);
        printf("信号内容: %s\n", param);
    }
}

static void cleanup_server()
{
    DBusError error;
    char rule[256];

    if (!g_connection)
    {
        return;
    }

    dbus_error_init(&error);

    /* 移除信号匹配规则 */
    snprintf(rule, sizeof(rule),
             "type='signal',interface='%s',member='%s'",
             TEST_INTERFACE_NAME, TEST_SIGNAL_NAME);

    dbus_bus_remove_match(g_connection, rule, &error);
    if (dbus_error_is_set(&error))
    {
        fprintf(stderr, "移除信号规则失败: %s\n", error.message);
        dbus_error_free(&error);
    }

    /* 释放服务名 */
    dbus_bus_release_name(g_connection, TEST_SERVICE_NAME, &error);
    if (dbus_error_is_set(&error))
    {
        fprintf(stderr, "释放服务名失败: %s\n", error.message);
        dbus_error_free(&error);
    }

    /* 关闭连接 */
    dbus_connection_unref(g_connection);
    g_connection = NULL;

    printf("服务端资源清理完成\n");

    /* 重置计数器 */
    g_signal_handler_count = 0;
    g_method_handler_count = 0;
}

/**
 * @brief 高效处理接收到的信号
 */
static void handle_signals_efficiently(DBusMessage *message)
{
    const char *interface = dbus_message_get_interface(message);
    const char *member = dbus_message_get_member(message);

    if (!interface || !member)
    {
        fprintf(stderr, "接收到无效的信号消息\n");
        return;
    }

    printf("收到信号: %s.%s\n", interface, member);

    /* 在注册表中查找匹配的处理器 */
    for (int i = 0; i < g_signal_handler_count; i++)
    {
        if (strcmp(g_signal_handlers[i].interface, interface) == 0 &&
            strcmp(g_signal_handlers[i].member, member) == 0)
        {
            /* 找到匹配的处理器，执行回调 ，需优化放到队列再执行*/
            g_signal_handlers[i].handler(message);
            return;
        }
    }

    /* 未找到处理器，使用默认处理 */
    printf("未找到对应的信号处理器，使用默认处理\n");
    handle_signal_default(message);
}

/**
 * @brief 高效处理接收到的方法调用
 */
static DBusHandlerResult handle_methods_efficiently(DBusConnection *connection, DBusMessage *message)
{
    const char *interface = dbus_message_get_interface(message);
    const char *member = dbus_message_get_member(message);

    if (!interface || !member)
    {
        fprintf(stderr, "接收到无效的方法调用消息\n");
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }

    printf("收到方法调用: %s.%s\n", interface, member);

    /* 在注册表中查找匹配的处理器 */
    for (int i = 0; i < g_method_handler_count; i++)
    {
        if (strcmp(g_method_handlers[i].interface, interface) == 0 &&
            strcmp(g_method_handlers[i].member, member) == 0)
        {
            /* 找到匹配的处理器，执行回调 ，需优化放到队列再执行*/
            return g_method_handlers[i].handler(connection, message);
        }
    }

    /* 未找到处理器，发送方法未找到错误 */
    printf("未找到对应的方法处理器，发送错误回复\n");
    DBusMessage *error_reply = dbus_message_new_error(message,
                                                      DBUS_ERROR_UNKNOWN_METHOD, "Method not found");
    if (error_reply)
    {
        dbus_connection_send(connection, error_reply, NULL);
        dbus_connection_flush(connection);
        dbus_message_unref(error_reply);
        return DBUS_HANDLER_RESULT_HANDLED;
    }
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

static void run_message_loop()
{
    printf("进入消息循环，等待消息...\n");
    printf("按Ctrl+C退出程序\n");

    while (TRUE)
    {
        /* 使用read_write_dispatch自动处理消息分发 */
        if (!dbus_connection_read_write_dispatch(g_connection, 100))
        {
            /* 连接已断开 */
            printf("D-Bus连接已断开\n");

            /* 进入重连循环 */
            while (TRUE)
            {
                if (reconnect_dbus())
                {
                    printf("重连成功，继续消息循环\n");
                    break;
                }

                printf("重连失败，3秒后重试...\n");
                sleep(3);
            }
        }
    }
}

static DBusHandlerResult message_filter(DBusConnection *connection,
                                        DBusMessage *message,
                                        void *user_data)
{
    // 加队列在另外线程处理
    if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
    {
        handle_signals_efficiently(message);
        return DBUS_HANDLER_RESULT_HANDLED;
    }
    else if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
    {
        return handle_methods_efficiently(connection, message);
    }

    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

/**
 * @brief 重连D-Bus服务
 */
static int reconnect_dbus()
{
    DBusError error;
    int ret;

    printf("正在尝试重连D-Bus...\n");

    /* 如果之前的连接还存在，先清理 */
    if (g_connection)
    {
        dbus_connection_unref(g_connection);
        g_connection = NULL;
    }

    dbus_error_init(&error);

    /* 重新连接到系统总线 */
    g_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
    if (dbus_error_is_set(&error))
    {
        fprintf(stderr, "重连D-Bus失败: %s\n", error.message);
        dbus_error_free(&error);
        return FALSE;
    }

    if (!g_connection)
    {
        fprintf(stderr, "重连D-Bus失败，返回NULL连接\n");
        return FALSE;
    }

    /* 重新请求服务名 */
    ret = dbus_bus_request_name(g_connection, TEST_SERVICE_NAME,
                                DBUS_NAME_FLAG_REPLACE_EXISTING, &error);
    if (dbus_error_is_set(&error))
    {
        fprintf(stderr, "重连时请求服务名失败: %s\n", error.message);
        dbus_error_free(&error);
        dbus_connection_unref(g_connection);
        g_connection = NULL;
        return FALSE;
    }

    if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER &&
        ret != DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER)
    {
        fprintf(stderr, "重连时获取服务名失败\n");
        dbus_connection_unref(g_connection);
        g_connection = NULL;
        return FALSE;
    }

    /* 重新添加过滤器 */
    dbus_connection_add_filter(g_connection, message_filter, NULL, NULL);

    /* 重新设置信号监听 */
    if (!setup_signal_listeners())
    {
        fprintf(stderr, "重连时设置信号监听失败\n");
        dbus_connection_unref(g_connection);
        g_connection = NULL;
        return FALSE;
    }

    printf("D-Bus重连成功\n");
    return TRUE;
}

#include <signal.h>

static void signal_handler(int sig)
{
    printf("\n收到退出信号，正在清理资源...\n");
    cleanup_server();
    exit(0);
}

int main()
{
    printf("=== D-Bus服务端测试程序 ===\n");

    /* 注册信号处理器 */
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);

    if (!initialize_server())
    {
        fprintf(stderr, "服务端初始化失败\n");
        return 1;
    }

    if (!setup_signal_listeners())
    {
        fprintf(stderr, "设置信号监听失败\n");
        cleanup_server();
        return 1;
    }

    /* 注册各种D-Bus信号处理器 */
    register_signal_handler(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, handle_test_signal);
    /* 注册各种D-Bus方法处理器 */
    register_method_handler(TEST_INTERFACE_NAME, TEST_METHOD_NAME, handle_test_method_call);
    run_message_loop();
    cleanup_server();
    return 0;
}
